import Konva from "konva";
import { ref } from "vue";
import chargeIcon from "@/assets/images/common/charge_icon.png";
import robotIcon from "@/assets/images/common/robot_icon.png";

export default function () {
  const stage = ref();
  const layer = ref();
  const image = ref();
  const group = ref();
  const imageScale = ref();
  const loading = ref();

  // 初始化舞台
  function initStage(container, width, height) {
    // 创建舞台
    stage.value = new Konva.Stage({ container, height, width });
    // 创建图层
    layer.value = new Konva.Layer({
      draggable: true,
      dragBoundFunc: () => ({ x: 0, y: 0 }),
    });
    image.value = new Konva.Image();
    group.value = new Konva.Group();
    layer.value.add(image.value).add(group.value);
    stage.value.add(layer.value);
    layer.value.on("wheel", layerZoom);
  }

  // 初始化背景图
  function initImage(url) {
    return new Promise((resolve) => {
      loading.value = true;
      group.value.removeChildren();
      const img = new Image();
      img.src = url;
      img.onload = () => {
        loading.value = false;
        imageScale.value = stage.value.height() / img.height;
        stage.value.width(img.width * imageScale.value);
        image.value.image(img);
        const { width, height } = stage.value.size();
        image.value.size({ width, height });
        resolve();
      };
    });
  }

  // 清空图层
  function clearLayer() {
    group.value.removeChildren();
  }

  // 图层缩放事件
  function layerZoom(e) {
    // 取消默认事件
    e.evt.preventDefault();
    // 缩放比例
    const scaleBy = 1.2;
    let newScale = layer.value.scaleX();
    if (e.evt.deltaY < 0) {
      newScale = newScale * scaleBy;
    } else {
      newScale = newScale / scaleBy < 1 ? 1 : newScale / scaleBy;
    }
    handleZoomCenter(newScale);
    layer.value.scale({ x: newScale, y: newScale });
    handleZoomOutScope();
  }

  // 处理缩放中心
  function handleZoomCenter(newScale) {
    const pointerPosition = layer.value.getRelativePointerPosition();
    const pointXScale = pointerPosition.x / stage.value.width();
    const pointYScale = pointerPosition.y / stage.value.height();
    // 缩放前图层宽高
    const oldScale = layer.value.scaleX();
    const oldWidth = stage.value.width() * oldScale;
    const oldHeight = stage.value.height() * oldScale;
    // 缩放后图层宽高
    const newWidth = stage.value.width() * newScale;
    const newHeight = stage.value.height() * newScale;
    // 缩放后图层位置
    layer.value.position({
      x: layer.value.x() - (newWidth - oldWidth) * pointXScale,
      y: layer.value.y() - (newHeight - oldHeight) * pointYScale,
    });
  }

  // 处理缩放范围
  function handleZoomOutScope() {
    const scale = layer.value.scaleX();
    const leftX = layer.value.x();
    const rightX = layer.value.x() + stage.value.width() * scale;
    const topY = layer.value.y();
    const bottomY = layer.value.y() + stage.value.height() * scale;
    if (leftX > 0) {
      layer.value.x(0);
    }
    if (rightX < stage.value.width()) {
      layer.value.x(-(stage.value.width() * (scale - 1)));
    }
    if (topY > 0) {
      layer.value.y(0);
    }
    if (bottomY < stage.value.height()) {
      layer.value.y(-(stage.value.height() * (scale - 1)));
    }
    // 处理缩放后拖拽范围
    const maxDragOffset = {
      x: -(stage.value.width() * (scale - 1)),
      y: -(stage.value.height() * (scale - 1)),
    };
    layer.value.dragBoundFunc((pos) => {
      let x = 0;
      let y = 0;
      if (pos.x > 0) {
        x = 0;
      } else if (pos.x <= maxDragOffset.x) {
        x = maxDragOffset.x;
      } else {
        x = pos.x;
      }
      if (pos.y > 0) {
        y = 0;
      } else if (pos.y <= maxDragOffset.y) {
        y = maxDragOffset.y;
      } else {
        y = pos.y;
      }
      return { x, y };
    });
  }

  // 绘制路径
  function drawPath(list) {
    const group = layer.value.children[1];
    group.removeChildren();
    if (list.length > 1) {
      const points = [];
      list.forEach((point) => {
        points.push(point.x);
        points.push(point.y);
      });
      group.add(new Konva.Line({ stroke: "#f90", strokeWidth: 1, points }));
    }
    list.forEach((i, n) => {
      const point = new Konva.Group({ x: i.x, y: i.y });
      const text = String(n + 1);
      const circle = new Konva.Circle({ radius: 3, fill: "#e33" });
      const marker = new Konva.Text({ text, fontSize: 3, fill: "#fff" });
      marker.offset({ x: marker.width() / 2, y: 1.2 });
      point.add(circle).add(marker);
      group.add(point);
    });
  }

  // 预览路径
  function previewPath(list) {
    list.forEach((element) => {
      element.x *= imageScale.value;
      element.y *= imageScale.value;
    });
    drawPath(list);
  }

  // 处理路径数据
  function handlePathData(list) {
    const route = [];
    list.forEach((element) => {
      route.push({
        x: Number((element.x / imageScale.value).toFixed(2)),
        y: Number((element.y / imageScale.value).toFixed(2)),
        angle: 0,
      });
    });
    for (let i = 0; i < route.length - 1; i++) {
      let x = route[i + 1].x - route[i].x;
      let y = route[i + 1].y - route[i].y;
      if (route[i].x > route[i + 1].x && route[i].y > route[i + 1].y) {
        route[i].angle = -(Math.atan2(y, x) + Math.PI / 2);
      }
      if (route[i].x < route[i + 1].x && route[i].y < route[i + 1].y) {
        route[i].angle = Math.abs(Math.atan2(y, x) - Math.PI / 2);
      }
      if (route[i].x > route[i + 1].x && route[i].y < route[i + 1].y) {
        route[i].angle = -(Math.atan2(y, x) - Math.PI / 2);
      }
      if (route[i].x < route[i + 1].x && route[i].y > route[i + 1].y) {
        route[i].angle = Math.PI - (Math.atan2(y, x) + Math.PI / 2);
      }
      route[i].angle = Number(route[i].angle.toFixed(2));
    }
    let str = "";
    route.forEach((i) => {
      str += `${i.x},${i.y},${i.angle};`;
    });
    return {
      raw: JSON.stringify(route),
      route: str.slice(0, str.length - 1),
    };
  }

  // 绘制充电点
  function drawCharge(list) {
    const group = layer.value.children[1];
    group.removeChildren();
    const img = new Image();
    img.src = chargeIcon;
    img.onload = () => {
      const image = new Konva.Image({
        width: 2.2,
        height: 3,
        x: list[0].x,
        y: list[0].y,
        image: img,
        draggable: true,
      });
      image.offset({ x: image.width() / 2, y: image.width() / 2 });
      group.add(image);
      var trans = new Konva.Transformer({
        resizeEnabled: false,
      });
      group.add(trans);
      trans.nodes([image]);
    };
  }

  // 预览充电点
  function previewCharge(x, y, rotation) {
    const group = layer.value.children[1];
    group.removeChildren();
    const img = new Image();
    img.src = chargeIcon;
    img.onload = () => {
      const image = new Konva.Image({
        width: 2.2,
        height: 3,
        x: x * imageScale.value,
        y: y * imageScale.value,
        image: img,
        draggable: true,
        rotation: -rotation,
      });
      image.offset({ x: image.width() / 2, y: image.width() / 2 });
      group.add(image);
    };
  }

  // 查看机器人位置
  function showRobot(x, y) {
    const group = layer.value.children[1];
    group.removeChildren();
    const img = new Image();
    img.src = robotIcon;
    img.onload = () => {
      const image = new Konva.Image({
        width: 2.2,
        height: 3,
        x: x * imageScale.value,
        y: y * imageScale.value,
        image: img,
      });
      image.offset({ x: image.width() / 2, y: image.width() / 2 });
      group.add(image);
    };
  }

  const pointData = ref([]);

  function drawPoint(icon) {
    group.value.removeChildren();
    const img = new Image();
    img.src = icon;
    img.onload = () => {
      const image = new Konva.Image({
        width: 5,
        height: 5,
        x: pointData.value[0].x,
        y: pointData.value[0].y,
        image: img,
        draggable: true,
      });
      image.offset({ x: image.width() / 2, y: image.width() / 2 });
      group.value.add(image);
      const trans = new Konva.Transformer({ resizeEnabled: false });
      trans.nodes([image]);
      group.value.add(trans);
    };
  }

  function previewPoint(icon, list) {
    group.value.removeChildren();
    list.forEach((item) => {
      const img = new Image();
      img.src = icon;
      img.onload = () => {
        const image = new Konva.Image({
          width: 5,
          height: 5,
          x: item.x * imageScale.value,
          y: item.y * imageScale.value,
          image: img,
          rotation: item.rotation,
        });
        image.offset({ x: image.width() / 2, y: image.width() / 2 });
        group.value.add(image);
        const trans = new Konva.Transformer({ resizeEnabled: false });
        trans.nodes([image]);
        group.value.add(trans);
      };
    });
  }

  function handlePointData() {
    let { x, y, rotation: theta = 0 } = group.value.children[0].attrs;
    x = Number((x / imageScale.value).toFixed(2));
    y = Number((y / imageScale.value).toFixed(2));
    if (theta === 0) {
      theta = Math.PI;
    } else if (theta < 0) {
      theta = -((180 + theta) * Math.PI) / 180;
    } else if (theta > 0) {
      theta = ((180 - theta) * Math.PI) / 180;
    }
    return {
      x: y,
      y: x,
      theta: Number(theta.toFixed(2)),
    };
  }

  return {
    stage,
    layer,
    group,
    imageScale,
    loading,
    pointData,
    drawPoint,
    previewPoint,
    handlePointData,
    initStage,
    initImage,
    drawPath,
    previewPath,
    handlePathData,
    clearLayer,
    drawCharge,
    previewCharge,
    showRobot,
  };
}
